POV-Ray : Newsgroups : povray.binaries.images : the Utah teapot is older than you think! : Re: the Utah teapot is older than you think! Server Time
1 Aug 2024 08:19:57 EDT (-0400)
  Re: the Utah teapot is older than you think!  
From: Bill Pragnell
Date: 7 Feb 2009 16:00:00
Message: <web.498df5d42cee23ee7da89d350@news.povray.org>
Right, here's the magic incantation:

// 'Encase' places objects over the surface of another object.
// Call this macro from inside union or merge for greater flexibility.
//
// baseobj - object identifier - the target object (must not be infinite).
// componentobj - object identifier - the object to be copied over the surface
of the target object.
// randy - yes/no - should componentobj be randomly rotated around the normal
when placed? (yes for grass etc)
// randxy - yes/no - should componentobj be randomly oriented before scaling and
placement? (yes for rocks etc)
// dx - float - grid size; probably similar to average object separation after
placement.
// scal1 - float - scale factor of componentobj in-plane (relative to dx)
// scal2 - float - scale factor of componentobj along normal (relative to dx)
// sd - seed - the random seed to be used.
//
#macro Encase(baseobj, componentobj, randy, randxy, dx, scal1, scal2, sd)
  #local minext = min_extent(baseobj);
  #local maxext = max_extent(baseobj);
  #local xwid = maxext.x - minext.x;
  #local ywid = maxext.y - minext.y;
  #local zwid = maxext.z - minext.z;
  #local norm = <0, 0, 0>;
  #local dirs = array[6] { x, -x, y, -y, z, -z }
  #local zp = minext.z + dx/2;
  #while (zp < maxext.z)
    #local yp = minext.y + dx/2;
    #while (yp < maxext.y)
      #local xp = minext.x + dx/2;
      #while (xp < maxext.x)
        #local startpos = <xp+dx*(rand(sd)-0.5), yp+dx*(rand(sd)-0.5),
zp+dx*(rand(sd)-0.5)>;
        #local n = 0;
        #local trans = transform { rotate x*rand(sd)*90 rotate y*rand(sd)*90 }
        #while ((n < 6))
          #local dir = vtransform(dirs[n], trans);
          #local spoint = trace(baseobj, startpos, dir, norm);
          #local sdist = vlength(spoint-startpos);
          #if ((sdist < dx) & (vlength(norm) > 0))
            object {
              componentobj
              #if (randy) rotate y*rand(sd) #end
              #if (randxy) rotate x*rand(sd)*360 rotate y*rand(sd)*360 #end
              scale <scal1*dx, scal2*dx, scal1*dx>
              Point_At_Trans(norm) translate spoint }
          #end
          #local n = n + 1;
        #end // direction loop
        #local xp = xp + dx;
      #end // x loop
      #local yp = yp + dx;
    #end // y loop
    #local zp = zp + dx;
  #end // z loop
#end

// usage example:
#declare TestTorus = torus { 2, 1 }
#declare TestBall = sphere { <0,0,0>, 1 }
#declare r1 = seed(0);
Encase(TestTorus, TestBall, no, no, 0.2, 0.5, 0.5, r1)


Hope it's useful!
Bill


Post a reply to this message

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.